﻿// Decompiled with JetBrains decompiler
// Type: Microsoft.InfoCards.PinProtectionHelper
// Assembly: infocard, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// MVID: 8E14765A-6610-409A-BA36-099A0642905D
// Assembly location: E:\git\ALLIDA\windll\infocard.exe

using Microsoft.InfoCards.Diagnostics;
using System;
using System.IO;
using System.Security.Cryptography;

namespace Microsoft.InfoCards
{
  internal class PinProtectionHelper
  {
    private RijndaelManaged m_aes = new RijndaelManaged();
    private const int InfoCardPKCS5IterationCount = 1000;
    public const int SaltSize = 16;
    private const int AESBlockByteLength = 16;
    private const int AESKeyByteLength = 32;
    private const byte EncryptForPinProtectionVersion = 2;
    private const int VersionOffset = 0;
    private const int SaltOffset = 1;
    private const int IterationsOffset = 17;
    private const int IVOffset = 21;
    private const int EncryptedDataOffset = 37;
    private PasswordDeriveBytes m_pkcs5;
    private byte[] m_key;

    public PinProtectionHelper(string pin)
    {
      RNGCryptoServiceProvider cryptoServiceProvider = new RNGCryptoServiceProvider();
      byte[] numArray = new byte[16];
      cryptoServiceProvider.GetBytes(numArray);
      this.m_pkcs5 = new PasswordDeriveBytes(pin, numArray, "SHA256", 1000);
      this.m_key = this.m_pkcs5.GetBytes(32);
      this.m_aes.Padding = PaddingMode.PKCS7;
      this.m_aes.Mode = CipherMode.CBC;
      this.m_aes.BlockSize = 128;
      this.m_aes.KeySize = this.m_key.Length * 8;
      this.m_aes.GenerateIV();
    }

    public PinProtectionHelper(string pin, byte[] serializedParameters)
    {
      if ((byte) 2 != serializedParameters[0])
        throw InfoCardTrace.ThrowHelperError((Exception) new InvalidCardException(SR.GetString("ServiceCardDecryptionFailed")));
      byte[] rgbSalt = new byte[16];
      Array.Copy((Array) serializedParameters, 1, (Array) rgbSalt, 0, 16);
      uint uint32 = BitConverter.ToUInt32(serializedParameters, 17);
      this.m_pkcs5 = new PasswordDeriveBytes(pin, rgbSalt, "SHA256", (int) uint32);
      this.m_key = this.m_pkcs5.GetBytes(32);
      this.m_aes.Padding = PaddingMode.PKCS7;
      this.m_aes.Mode = CipherMode.CBC;
      this.m_aes.BlockSize = 128;
      this.m_aes.KeySize = this.m_key.Length * 8;
      byte[] numArray = new byte[16];
      Array.Copy((Array) serializedParameters, 21, (Array) numArray, 0, numArray.Length);
      this.m_aes.IV = numArray;
    }

    public byte[] EncryptMasterKey(byte[] toEncrypt)
    {
      byte[] buffer = this.Encrypt(toEncrypt);
      using (MemoryStream memoryStream = new MemoryStream())
      {
        memoryStream.WriteByte((byte) 2);
        memoryStream.Write(this.m_pkcs5.Salt, 0, this.m_pkcs5.Salt.Length);
        memoryStream.Write(BitConverter.GetBytes((uint) this.m_pkcs5.IterationCount), 0, 4);
        memoryStream.Write(this.m_aes.IV, 0, this.m_aes.IV.Length);
        memoryStream.Write(buffer, 0, buffer.Length);
        return memoryStream.ToArray();
      }
    }

    public static int EncryptedMasterKeySize
    {
      get
      {
        return 85;
      }
    }

    public byte[] Encrypt(byte[] toEncrypt)
    {
      using (ICryptoTransform encryptor = this.m_aes.CreateEncryptor(this.m_key, this.m_aes.IV))
      {
        using (MemoryStream memoryStream = new MemoryStream())
        {
          try
          {
            using (CryptoStream cryptoStream = new CryptoStream((Stream) memoryStream, encryptor, CryptoStreamMode.Write))
            {
              cryptoStream.Write(toEncrypt, 0, toEncrypt.Length);
              cryptoStream.FlushFinalBlock();
              return memoryStream.ToArray();
            }
          }
          catch (CryptographicException ex)
          {
            throw InfoCardTrace.ThrowHelperError((Exception) new InvalidCardException(SR.GetString("ServiceCardEncryptionFailed"), (Exception) ex));
          }
        }
      }
    }

    public byte[] DecryptMasterKey(byte[] toDecrypt)
    {
      byte[] encrypted = new byte[toDecrypt.Length - 37];
      Array.Copy((Array) toDecrypt, 37, (Array) encrypted, 0, toDecrypt.Length - 37);
      return this.Decrypt(encrypted);
    }

    public byte[] Decrypt(byte[] encrypted)
    {
      using (ICryptoTransform decryptor = this.m_aes.CreateDecryptor(this.m_key, this.m_aes.IV))
      {
        using (MemoryStream memoryStream = new MemoryStream(encrypted))
        {
          try
          {
            using (CryptoStream cryptoStream = new CryptoStream((Stream) memoryStream, decryptor, CryptoStreamMode.Read))
            {
              byte[] buffer = new byte[encrypted.Length];
              int length = cryptoStream.Read(buffer, 0, buffer.Length);
              byte[] numArray = new byte[length];
              Array.Copy((Array) buffer, (Array) numArray, length);
              return numArray;
            }
          }
          catch (CryptographicException ex)
          {
            throw InfoCardTrace.ThrowHelperError((Exception) new InvalidCardException(SR.GetString("ServiceCardDecryptionFailed"), (Exception) ex));
          }
        }
      }
    }
  }
}
